/****************************************************************************
*  ALi Corporation, All Rights Reserved. 2010 Copyright (C)
*  File: isdbtcc_dec_osd.c
*  Description: control cc display functions
*  History:
*      Date        	Author         	Version   Comment
*      ====        	======         =======   =======
*  1.  2010.04.26  Vicky Hsu      	  0.1.000   	create for isdbtcc
****************************************************************************/
/*******************
* INCLUDE FILES    *
********************/
#include <basic_types.h>
#include <mediatypes.h>
#include <api/libc/printf.h>
#include <hld/osd/osddrv.h>
#include <hld/hld_dev.h>
#include <hld/isdbtcc/isdbtcc_dec.h>
#include <hld/dis/vpo.h>
#include <api/libisdbtcc/lib_isdbtcc.h>
#include <api/libisdbtcc/isdbtcc_osd.h>
#include "isdbtcc_dec_osd.h"
/*******************
* EXPORTED DATA    *
********************/

/*******************
* LOCAL MACROS     *
********************/
#define DBG_CS	1
/*******************
* STATIC DATA      *
********************/
extern struct isdbtcc_config_par g_isdbtcc_config_par;
static BOOL gfCcShow=FALSE;	
static BOOL gfCcPreShow=FALSE;
static BOOL gfCcEnbaleShow=FALSE;	
//Local CC_OSD status: TRUE: ready and ok to use, FASLE: need to call isdbtcc_osd_enter() first
static BOOL gfInSubtDecoding=FALSE;
static UINT8 gbCurRegion= 0;	// region id of close caption , create via isdbtcc_osd_enter()
static VSCR gVscr ;			// virtual screen for close caption
static struct osd_device *gOsdDev;

extern UINT16 gwForX;
extern UINT16 gwForY;
extern UINT16 gwAreaX;
extern UINT16 gwAreaY;
extern UINT16 gwDispX;
extern UINT16 gwDispY;
extern UINT16 gwCharX;
extern UINT16 gwCharY;
extern UINT16 gwSpaceX;
extern UINT16 gwSpaceY;

extern UINT8 gbx2;	//Max X
extern UINT8 gby2;		//Max Y
extern UINT8 gbx;		//Active X
extern UINT8 gby;		//Active Y
extern UINT8 gbFcol;	//Foreground Color
extern UINT8 gbBcol;	//Background Color
extern UINT8 gbRcol;	//Raster Color

static BOOL gfYcbcr=FALSE;
/*******************
* LOCAL TYPEDEFS   *
********************/
#define FONTSIZE		FONT_18X18
/**********************
* FUNCTION PROTOTYPES *
***********************/
void ICC_FillChar(UINT16 x, UINT16 y,UINT16 w,UINT16 h,UINT8 bg_color);
const osd_scale_param m_osd_cc_scale_map_540[] = 
{
    {PAL, 			8,15,6,16,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 576}*/},
    {PAL_N, 		8,15,6,16,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 576}*/},

    {NTSC, 		8,9,6,8,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 480}*/},
    {NTSC_443, 	8,9,6,8,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 480}*/},
    {PAL_60, 		8,9,6,8,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 480}*/},
    {PAL_M, 		8,9,6,8,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 480}*/},

    {LINE_720_25, 	3,3,4,4,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1280, 720 }*/},
    {LINE_720_30, 	3,3,4,4,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1280, 720}*/},

    {LINE_1080_25, 1,1,2,2,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
    {LINE_1080_30, 1,1,2,2,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
    {LINE_1080_50, 1,1,2,2,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
    {LINE_1080_60, 1,1,2,2,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
    {LINE_1080_24, 1,1,2,2,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
};

const osd_scale_param m_osd_cc_scale_map_480[] = 
{
    {PAL, 			1,5,1,6,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 576}*/},
    {PAL_N, 		1,5,1,6,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 576}*/},

    {NTSC, 		1,1,1,1,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 480}*/},
    {NTSC_443, 	1,1,1,1,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 480}*/},
    {PAL_60, 		1,1,1,1,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 480}*/},
    {PAL_M, 		1,1,1,1,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 480}*/},

    {LINE_720_25, 	9,2,16,3,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1280, 720 }*/},
    {LINE_720_30, 	9,2,16,3,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1280, 720}*/},

    {LINE_1080_25, 3,4,8,9,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
    {LINE_1080_30, 3,4,8,9,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
    {LINE_1080_50, 3,4,8,9,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
    {LINE_1080_60, 3,4,8,9,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
    {LINE_1080_24, 3,4,8,9,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
};
static const osd_scale_param m_osd_scale_map_640[] = 
{
    {PAL, 			(ISDBT_CC_OSD_LEFT+ISDBT_CC_OSD_WIDTH),15,720,16,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 576}*/},
    {PAL_N, 		(ISDBT_CC_OSD_LEFT+ISDBT_CC_OSD_WIDTH),15,720,16,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 576}*/},

    {NTSC, 		(ISDBT_CC_OSD_LEFT+ISDBT_CC_OSD_WIDTH),9,720,8,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 480}*/},
    {NTSC_443, 	(ISDBT_CC_OSD_LEFT+ISDBT_CC_OSD_WIDTH),9,720,8,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 480}*/},
    {PAL_60, 		(ISDBT_CC_OSD_LEFT+ISDBT_CC_OSD_WIDTH),9,720,8,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 480}*/},
    {PAL_M, 		(ISDBT_CC_OSD_LEFT+ISDBT_CC_OSD_WIDTH),9,720,8,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 720, 480}*/},

    {LINE_720_25, 	(ISDBT_CC_OSD_LEFT+ISDBT_CC_OSD_WIDTH),3,1280,4,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1280, 720 }*/},
    {LINE_720_30, 	(ISDBT_CC_OSD_LEFT+ISDBT_CC_OSD_WIDTH),3,1280,4,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1280, 720}*/},

    {LINE_1080_25, (ISDBT_CC_OSD_LEFT+ISDBT_CC_OSD_WIDTH),1,1920,2,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
    {LINE_1080_30, (ISDBT_CC_OSD_LEFT+ISDBT_CC_OSD_WIDTH),1,1920,2,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
    {LINE_1080_50, (ISDBT_CC_OSD_LEFT+ISDBT_CC_OSD_WIDTH),1,1920,2,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
    {LINE_1080_60, (ISDBT_CC_OSD_LEFT+ISDBT_CC_OSD_WIDTH),1,1920,2,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},
    {LINE_1080_24, (ISDBT_CC_OSD_LEFT+ISDBT_CC_OSD_WIDTH),1,1920,2,/*{UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT, 1920, 1080}*/},

};
static pcosd_scale_param ICC_get_scale_param(enum TVSystem eTVMode)
{
    UINT32 i,size_540,size_480,size=0,size_other;
    const osd_scale_param  *p_ui_map=(void*)NULL;
    size_540  = ARRAY_SIZE(m_osd_cc_scale_map_540);
    size_480  = ARRAY_SIZE(m_osd_cc_scale_map_480);
	size_other = ARRAY_SIZE(m_osd_scale_map_640);
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
	{
		size = size_other;
    	p_ui_map =m_osd_scale_map_640;
	}
	else
	{
    	switch(gwForY)		
    	{
    		case 540:		
      			size = size_540;
      			p_ui_map =m_osd_cc_scale_map_540;
				break;
    		case 480:		
      			size = size_480;
      			p_ui_map = m_osd_cc_scale_map_480;
				break;	
    	}
	}
	
    for (i = 0; i < size; i++)
    {
        if (p_ui_map[i].tv_sys == eTVMode)
        {
            return &(p_ui_map[i]);
        }
    }
    return &(p_ui_map[0]);
}

static BOOL osd_cc_adjust_region(UINT8 region_idx, struct OSDRect *pRegion)
{
	osd_region_param region_param;
	RET_CODE ret;	
	UINT32 osd_region_len=0;	
	
	
	pRegion->uWidth = ((pRegion->uWidth+0xf)&0xfffffff0); 
	
	osd_region_len=(pRegion->uWidth)*(pRegion->uHeight);
	if(osd_region_len>g_isdbtcc_config_par.g_buf_osd_len)
	{
		ICC_PRINTF("cc display size is too large\n");
		return FALSE;
	}
	
	MEMSET(&region_param,0,sizeof(osd_region_param));  
	
	ret = OSDDrv_IoCtl((HANDLE)gOsdDev, OSD_IO_GET_REGION_INFO, (UINT32)&region_param);
	if (ret != RET_SUCCESS)
		return FALSE;
			
	region_param.region_id = region_idx;
	region_param.region_x = pRegion->uLeft;
	region_param.region_y = pRegion->uTop;
	region_param.region_w = pRegion->uWidth;
	region_param.region_h = pRegion->uHeight;
	region_param.bitmap_x = 0;
	region_param.bitmap_y = 0;
	region_param.bitmap_w =  pRegion->uWidth;
	region_param.bitmap_h = pRegion->uHeight;
	region_param.pixel_pitch = pRegion->uWidth;
	region_param.bitmap_addr =g_isdbtcc_config_par.g_buf_osd_addr;
	ret = OSDDrv_DeleteRegion((HANDLE)gOsdDev, region_idx);
			
	if (ret != RET_SUCCESS)
	{
		ICC_PRINTF("delete fail\n");		
		//SDBBP();
		return FALSE;
	}
			
	ret = OSDDrv_IoCtl((HANDLE)gOsdDev, OSD_IO_CREATE_REGION, (UINT32)&region_param);
		   
	if (ret != RET_SUCCESS)
	{
		ICC_PRINTF("create fail\n");		
		//SDBBP();
		return FALSE;
	}	
	return TRUE;
	}
/********************************************
* NAME: cc_osd_enter
*       init cc osd
*
* Returns : void
* Parameter     				Flow    Description
* ------------------------------------------------------------------------------
* None
* ------------------------------------------------------------------------------
* Additional information:

******************************************/
void isdbtcc_osd_enter(void)
{
    	struct OSDPara	tOpenPara;
	struct OSDRect	tOpenRect;
	struct OSDRect  r;
	enum TVSystem tvsys;
	RET_CODE tRet;
	UINT16 bAreax=0,bAreay=0;		
	UINT8 bRcol=gbRcol;

	gfCcEnbaleShow=TRUE;		
	if((0>=gwAreaX) ||(0>=gwAreaY))
		goto LEAVE;
	if(TRUE==gfCcShow)	
		goto LEAVE;
	
	if(TRUE==gfCcPreShow)
		goto LEAVE;
	else
		gfCcPreShow=TRUE;
	
	while(gfInSubtDecoding == TRUE)
    	{
      		OS_TaskSleep(1);
    	}
	vpo_ioctl((struct vpo_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DIS), VPO_IO_GET_OUT_MODE, (UINT32)(&tvsys));	
	tOpenPara.eMode= OSD_256_COLOR;
	tOpenPara.uGAlphaEnable= FALSE;	
	tOpenPara.uGAlpha= 0x0f;
	tOpenPara.uPalletteSel = 0;
	gOsdDev = (struct osd_device *)dev_get_by_id(HLD_DEV_TYPE_OSD, g_isdbtcc_config_par.isdbtcc_osd_layer_id);
	if(NULL==gOsdDev)	{ICC_PRINTF("Assert due to null osd_dev!\n");}
	
	#if 1
		tRet=OSDDrv_Close((HANDLE)gOsdDev);		
			if(RET_SUCCESS!=tRet)	{ICC_PRINTF("Fail to Close osd_dev.\n");}
        OSDDrv_ShowOnOff((HANDLE)gOsdDev, OSDDRV_OFF);      
		tRet=OSDDrv_Open((HANDLE)gOsdDev, &tOpenPara);		
			if(RET_SUCCESS!=tRet)	{ICC_PRINTF("Fail to Open osd_dev.\n");}
		//osal_task_sleep(20);
	#else
	OSDDrv_ShowOnOff((HANDLE)gOsdDev, OSDDRV_OFF);
	#endif

	bAreax=gwForX;
	bAreay=gwForY;
#ifndef ISDBT_CC_DECREASED_SIZE
	tOpenRect.uWidth = bAreax;
	tOpenRect.uHeight = bAreay;	
	tOpenRect.uLeft = 0;//(1280-bAreax)>>1;
	tOpenRect.uTop = 0;//(720-bAreay);
	ICC_PRINTF("\nTVSys(%d),",tvsys);
	//ICC_PRINTF("[%d,%d,%d,%d]\n",bAreax,bAreay,tOpenRect.uLeft,tOpenRect.uTop);
	
	tRet=OSDDrv_CreateRegion((HANDLE)gOsdDev, gbCurRegion, &(tOpenRect), &tOpenPara);
	if(RET_SUCCESS!=tRet)	
	{
		ICC_PRINTF("Fail to Create Region.\n");
	}
#else
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)		
		tOpenRect.uWidth=ISDBT_CC_OSD_WIDTH;
	else
		tOpenRect.uWidth=gwForX-gwDispX;
	tOpenRect.uHeight =(gby2+1)*(gwCharY+gwSpaceY);	
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)		
		tOpenRect.uLeft =ISDBT_CC_OSD_LEFT; 
	else
	tOpenRect.uLeft =gwDispX;//(1280-bAreax)>>1;
	tOpenRect.uTop = gwDispY;//(720-bAreay);
	ICC_PRINTF("\nTVSys(%d),",tvsys);
	
	tRet=osd_cc_adjust_region(0,&tOpenRect);
	if(TRUE!=tRet)	
	{
		ICC_PRINTF("Fail to Create Region.\n");
	}
#endif

	// ((struct osd_s3601_private*)gOsdDev->priv)->surface   // need to check
	tRet=OSDDrv_SetPallette((HANDLE)gOsdDev,(UINT8*)gbPallette, CC_COLOR_NUMBER, OSDDRV_YCBCR);
		if(RET_SUCCESS!=tRet)	{ICC_PRINTF("Fail to Set Pallette.\n");}

	gVscr.vR.uLeft = 0;
	gVscr.vR.uTop = 0;
	gVscr.vR.uWidth = tOpenRect.uWidth;
	gVscr.vR.uHeight = tOpenRect.uHeight;	

	
	#if 0	
	extern void* heap_ptr;
	ICC_PRINTF("15__Heap_PTR_in_isdbtcc_osd_enter,%x\n",heap_ptr);
	#endif
	
	#if 1
		gVscr.lpbScr = g_isdbtcc_config_par.g_buf_addr;
		MEMSET(gVscr.lpbScr,bRcol,g_isdbtcc_config_par.g_buf_len);	
	#else
	UINT8* bVscrBuf;			
	bVscrBuf = (UINT8 *)MALLOC((UINT32)(tOpenRect.uWidth)*(tOpenRect.uHeight));
	if(NULL==bVscrBuf)	{ICC_PRINTF("\nOh!Oh! Fail to alloc Disp Mem for CC!!!!\n");}
	gVscr.lpbScr = bVscrBuf;
	MEMSET(bVscrBuf,bRcol,(UINT32)(tOpenRect.uWidth)*(tOpenRect.uHeight));	
	#endif
	
	r.uLeft = 0;
	r.uTop = 0;
	r.uWidth =tOpenRect.uWidth;
	r.uHeight =tOpenRect.uHeight;	
	//tRet=OSDDrv_RegionFill((HANDLE)gOsdDev, gbCurRegion, &r, CC_TRANSPARENT);
	tRet=OSDDrv_RegionFill((HANDLE)gOsdDev, gbCurRegion, &r, bRcol);
	if(RET_SUCCESS!=tRet)	{ICC_PRINTF("Fail to Fill Region with %d Color.\n",bRcol);}
	//libc_printf("\ntvsys(%d),eOSDSys(%d)",tvsys,eOSDSys);

	enum OSDSys  eOSDSys;
#ifdef HDTV_SUPPORT
	if(tvsys == NTSC||tvsys == PAL_M||tvsys == PAL_60||tvsys == NTSC_443||tvsys == LINE_720_30||tvsys == LINE_1080_30)
		eOSDSys = OSD_NTSC;
	else
		eOSDSys = OSD_PAL;
#else
	if(tvsys == NTSC||tvsys == PAL_M||tvsys == PAL_60||tvsys == NTSC_443)
		eOSDSys = OSD_NTSC;
	else
		eOSDSys = OSD_PAL;
#endif

	if(	(gwForY==540)||(gwForY==480)	)
		{tRet=OSDDrv_Scale((HANDLE)gOsdDev,OSD_SCALE_WITH_PARAM,(UINT32)ICC_get_scale_param(tvsys));}		
	else
	{	
		tRet=OSDDrv_Scale((HANDLE)gOsdDev,OSD_VSCALE_TTX_SUBT,(UINT32)(&eOSDSys));
		ICC_PRINTF("\nNeed to Add Scale with Unexpected Format XY (i.e Neithor 960x540 Nor 720x480 !!!!!!!");
	}

	if( (NTSC==tvsys)||  (NTSC_443==tvsys) ||(PAL_M==tvsys)||(PAL_N==tvsys)||(PAL_60==tvsys)||(PAL==tvsys))
	{
		tRet=OSDDrv_Scale((HANDLE)gOsdDev, 	OSD_SET_SCALE_MODE, OSD_SCALE_FILTER);
	}
	
	if(RET_SUCCESS!=tRet)	{ICC_PRINTF("Fail to Scale.\n");}

	tRet=OSDDrv_ShowOnOff((HANDLE)gOsdDev, OSDDRV_ON);
	ICC_PRINTF(",ENTER CC OSD ");
	if(RET_SUCCESS!=tRet)	{ICC_PRINTF("Fai to Show On.\n");}
	gfCcShow = TRUE;	
	gfCcPreShow=FALSE;
LEAVE:	
	return;
}
/********************************************
* NAME: cc_osd_leave
*       destroy cc osd and return menu osd
*
* Returns : void
* Parameter     				Flow    Description
* ------------------------------------------------------------------------------
* None
* ------------------------------------------------------------------------------
* Additional information:
******************************************/

void isdbtcc_osd_leave()
{
	enum TVSystem tvsys;	
	gfCcEnbaleShow=FALSE;

	if(FALSE==gfCcShow)	
		goto LEAVE;
	
	while(gfInSubtDecoding == TRUE)
    	{
      		OS_TaskSleep(1);
    	}
	
	vpo_ioctl((struct vpo_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DIS), VPO_IO_GET_OUT_MODE, (UINT32)(&tvsys));	
	gOsdDev = (struct osd_device *)dev_get_by_id(HLD_DEV_TYPE_OSD, g_isdbtcc_config_par.isdbtcc_osd_layer_id);
	if(NULL!=gOsdDev)
	{
		if(TRUE==gfYcbcr)
		{
			osd_clut_ycbcr_out clut_ycbcr_out = {0,0,0,0};
			clut_ycbcr_out.layer = 0; // set layer number	
			clut_ycbcr_out.enable = 0;	
			clut_ycbcr_out.no_temp_buf = 1;	//notice, be careful to restore original value before call isdbtcc_osd_enter()
			OSDDrv_IoCtl((HANDLE)gOsdDev, OSD_IO_SET_YCBCR_OUTPUT, (UINT32)&clut_ycbcr_out);		
			gfYcbcr=FALSE;
		}
		OSDDrv_DeleteRegion((HANDLE)gOsdDev, gbCurRegion);
		OSDDrv_Close((HANDLE)gOsdDev);
		ICC_PRINTF(",Leave CC OSD ");
	}
	if(NULL!=gVscr.lpbScr)
		{FREE(gVscr.lpbScr);}
	gfCcShow = FALSE;
LEAVE:
return;
}
/********************************************
* NAME: CC_DrawChar1
*       draw cc osd
*
* Returns : void
* Parameter     				Flow    Description
* ------------------------------------------------------------------------------
* UINT16 x					In	pos_x of cc char	(input range as 0~31)
* UINT16 y					In	pos_y of cc char	(input range as 0~14)
* UINT8 fg_color				In	fg color of cc char
* UINT8 bg_color				In	bg color of cc char
* UINT16 character				In	cc char
* ------------------------------------------------------------------------------
* Additional information:
******************************************/
#ifndef ISDBT_CC_DECREASED_SIZE

void ICC_DrawChar1(UINT16 x, UINT16 y, UINT8 fg_color, UINT8 bg_color,UINT16 character)
{
	//Target
	struct OSDRect r;				// rectangle info  to display
	UINT8* pData; 				
	//Temp 
	UINT8 i=0, j=0;
	UINT16 wAdd=0;
	UINT8 data1=0;				//temp data to store data as fg or bg color	
	#define CHARMASK_BITORDER		5
	#define CHARMASK_BITS			32
	UINT32 charmask;			// 32bits, one by one bit check
	UINT16 bit_count;			// sum bits check num
	const UINT32*  char_addr=NULL;		// font data start points
	//Font Info
	UINT8 cc_actual_width=0;
	UINT8 cc_col=0;
	//========
	UINT16 wy,wx;

	UINT8 bwidth=gwCharX+gwSpaceX;;
	UINT8 bfonthight=gwCharY;
	UINT8 bheight=gwCharY+gwSpaceY;
	UINT8 bxend=gbx2;
	UINT8 byend=gby2;
	UINT16 wLeft=gwDispX;
	UINT16 wTop=gwDispY;	


	if(TRUE==gfCcEnbaleShow) 	
	{
		if(TRUE!=gfCcShow)			
		{
			if(TRUE!=gfCcPreShow)
			{
				isdbtcc_osd_enter();
			}
			else
			{
				goto LEAVE;
			}
		} 
	}
	else
	{
		goto LEAVE;
	}	
	
ENTER_SUBT_OSD_API();	
//Correct para if out of range
	y = (y>byend)?byend:y;	
	x = (x>bxend)?bxend:x;	
	
	wy=y*bheight+wTop;
	wx=x*bwidth+wLeft;
	
//Invoke corresponging font data
	for(i=0;i<CC_FONT_NUM;i++)
	{
		if(CC_FPOR[i]==character)	 {j=i;break;}	
	}
	if(CC_FONT_NUM==i)
	{
		ICC_PRINTF("No Found Font data(%x)\n",character);	
		LEAVE_SUBT_OSD_API();
		ICC_FillChar(x, y, 1, 1,bg_color);
		return;
	}

	for(i=0;i<=j;i++)
	{	
		cc_actual_width=CC_FPOR_width[i];	
		cc_col=((UINT16)cc_actual_width*bfonthight)>>CHARMASK_BITORDER;
		if(((UINT16)cc_actual_width*bfonthight)%CHARMASK_BITS)
			cc_col++;		
		if(i==j)
			break;
		wAdd+=cc_col;		
	}	
	char_addr=&CC_FPOR_data[wAdd];
		
	pData = gVscr.lpbScr+(UINT32)gVscr.vR.uWidth*wy+wx;
	for(i=0;i<bheight;i++)
	{
		MEMSET(pData+gVscr.vR.uWidth*i,bg_color,bwidth);
	}
	if(character < 0x20)
		{goto LEAVE ;}

	r.uLeft = wx;
	r.uTop = wy;
	r.uWidth = bwidth;
	r.uHeight = bheight;

	pData = gVscr.lpbScr+(UINT32)gVscr.vR.uWidth*wy+wx;			
	bit_count = 0;	

	//vertical normal , horizine normal	
     	for(i = 0 ;i < cc_col;i++)
     	{
     		charmask = 0x80000000;	
		for(j = 0 ;j < 32 ;j++)
		{
			if(bit_count >= (UINT16)cc_actual_width * bfonthight)	//char draw finished
				break;

			if( (bit_count!=0) && (bit_count %cc_actual_width ==0))	//one row finished, change to next
				{pData += (gVscr.vR.uWidth-cc_actual_width);}
			
			if(*char_addr & charmask)	
				{data1 = fg_color;	}	
			else						
				{data1 = bg_color;	}	
			
			*pData = data1;
			pData++;
			bit_count++;
			charmask >>=1;				
		}
		char_addr ++;
     	}
	// write Vscr data to osd frame buffer
	#if (DBG_CS==1)
	OSDDrv_RegionWrite((HANDLE)gOsdDev, gbCurRegion, &gVscr, &r);
	#endif
LEAVE:
	LEAVE_SUBT_OSD_API();
}
#else
void ICC_DrawChar1(UINT16 x, UINT16 y, UINT8 fg_color, UINT8 bg_color,UINT16 character)
{

	//Target
	struct OSDRect r;				// rectangle info  to display
	UINT8* pData; 				
	//Temp 
	UINT8 i=0, j=0;
	UINT16 wAdd=0;
	UINT8 data1=0;				//temp data to store data as fg or bg color	
	#define CHARMASK_BITORDER		5
	#define CHARMASK_BITS			32
	UINT32 charmask;			// 32bits, one by one bit check
	UINT16 bit_count;			// sum bits check num
	const UINT32*  char_addr=NULL;		// font data start points
	//Font Info
	UINT8 cc_actual_width=0;
	UINT8 cc_col=0;
	//========
	UINT16 wy,wx;
	UINT8 bwidth=0;
	UINT8* ptr=NULL;

	UINT8 bfonthight=gwCharY;
	UINT8 bheight=gwCharY+gwSpaceY;
	UINT8 bxend=gbx2;
	UINT8 byend=gby2;
	UINT16 wLeft=gwDispX;
	UINT16 wTop=gwDispY;	


	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
		 bwidth=ISDBT_CC_FONT_WIDTH;
	else
		 bwidth=gwCharX+gwSpaceX;
	if(TRUE==gfCcEnbaleShow) 	
	{
		if(TRUE!=gfCcShow)			
		{
			if(TRUE!=gfCcPreShow)
			{
				isdbtcc_osd_enter();
			}
			else
			{
				goto LEAVE;
			}
		} 
	}
	else
	{
		goto LEAVE;
	}	
	
	
ENTER_SUBT_OSD_API();	
//Correct para if out of range
	if(g_isdbtcc_config_par.isdbtcc_bgcolor_changed==TRUE)
	{
		if(bg_color!=0)
		{
			bg_color=0;
		}
		ptr=(UINT8*)&(gbPallette[fg_color*4]);
		OSDDrv_ModifyPallette((HANDLE)gOsdDev, bg_color, 0x10, 0x80, 0x80, 0x0f);
		OSDDrv_ModifyPallette((HANDLE)gOsdDev, fg_color, ptr[0], ptr[1], ptr[2], 0x0f);
	}
	y = (y>byend)?byend:y;	
	x = (x>bxend)?bxend:x;	
	
	wy=y*bheight+wTop;
	wx=x*bwidth+wLeft;
	//libc_printf("wx=%d,wy=%d,bheight=%d,bwidth=%d,wTop=%d,wLeft=%d\n",wx,wy,bheight,bwidth,wTop,wLeft);
//Invoke corresponging font data
	for(i=0;i<CC_FONT_NUM;i++)
	{
		if(CC_FPOR[i]==character)	 {j=i;break;}	
	}
	if(CC_FONT_NUM==i)
	{
		ICC_PRINTF("No Found Font data(%x)\n",character);	
		LEAVE_SUBT_OSD_API();
		ICC_FillChar(x, y, 1, 1,bg_color);
		return;
	}

	for(i=0;i<=j;i++)
	{	
		cc_actual_width=CC_FPOR_width[i];	
		cc_col=((UINT16)cc_actual_width*bfonthight)>>CHARMASK_BITORDER;
		if(((UINT16)cc_actual_width*bfonthight)%CHARMASK_BITS)
			cc_col++;		
		if(i==j)
			break;
		wAdd+=cc_col;		
	}	
	char_addr=&CC_FPOR_data[wAdd];
	gVscr.vR.uLeft =0;//r.uLeft;
	gVscr.vR.uTop = 0;//r.uTop;
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
		gVscr.vR.uWidth =ISDBT_CC_OSD_WIDTH;
	else
	gVscr.vR.uWidth =gwForX-gwDispX;
	gVscr.vR.uHeight =bheight*(gby2+1);
	
	gVscr.lpbScr =g_isdbtcc_config_par.g_buf_addr;	
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
		pData = gVscr.lpbScr+y*bheight*ISDBT_CC_OSD_WIDTH+x*bwidth;
	else
	pData = gVscr.lpbScr+(y*bheight)*(gwForX-gwDispX)+x*bwidth;
	
	
	
	for(i=0;i<bheight;i++)
	{
		MEMSET(pData+(gVscr.vR.uWidth)*i,bg_color,bwidth);
	}
	if(character < 0x20)
		{goto LEAVE ;}

	r.uLeft =x*bwidth;
	r.uTop =y*bheight;
	r.uWidth =bwidth;
	r.uHeight = bheight;
	
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
		pData = gVscr.lpbScr+y*bheight*ISDBT_CC_OSD_WIDTH+x*bwidth;
	else
	pData = gVscr.lpbScr+(y*bheight)*(gwForX-gwDispX)+x*bwidth;
		

	
	bit_count = 0;	

	//vertical normal , horizine normal	
     	for(i = 0 ;i < cc_col;i++)
     	{
     		charmask = 0x80000000;	
		for(j = 0 ;j < 32 ;j++)
		{
			if(bit_count >= (UINT16)cc_actual_width * bfonthight)	//char draw finished
				break;

			if( (bit_count!=0) && (bit_count %cc_actual_width ==0))	//one row finished, change to next
				{
					if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
						pData +=(ISDBT_CC_OSD_WIDTH-cc_actual_width);
					else
						pData +=((gwForX-gwDispX)-cc_actual_width);
				
				}
			
			if(*char_addr & charmask)	
				{data1 = fg_color;	}	
			else						
				{data1 = bg_color;	}	
			
			*pData = data1;
			pData++;
			bit_count++;
			charmask >>=1;				
		}
		//libc_printf("char=0x%x\n",*char_addr);
		char_addr ++;
     	}
	// write Vscr data to osd frame buffer
	#if (DBG_CS==1)
	
	//cc_rect_cpy(960,26, cc_Vscr2.lpbScr ,19,26,cc_Vscr.lpbScr,&(cc_Vscr2.vR),&(cc_Vscr.vR));
	OSDDrv_RegionWrite((HANDLE)gOsdDev, gbCurRegion, &gVscr, &r);
	#endif
LEAVE:
	LEAVE_SUBT_OSD_API();
}

#endif
/********************************************
* NAME: CC_FillChar
*       fill a rectanger with one color
*
* Returns : void
* Parameter     				Flow    Description
* ------------------------------------------------------------------------------
* UINT16 x					In	start pos_x of char
* UINT16 y					In	start pos_y of char
* UINT16 w					In	width (number of cc char)
* UINT16 h					In	high (number of cc char)
* UINT8 bg_color				In	bg color
* ------------------------------------------------------------------------------
* Additional information:
******************************************/
#ifndef ISDBT_CC_DECREASED_SIZE

void ICC_FillChar(UINT16 x, UINT16 y,UINT16 w,UINT16 h,UINT8 bg_color)
{
	UINT32 i;
	struct OSDRect r;	
	UINT8* pData; 
	UINT8 bwidth=gwCharX+gwSpaceX;
	UINT8 bheight=gwCharY+gwSpaceY;
	UINT8 bxend=gbx2;
	UINT8 byend=gby2;
	UINT16 wLeft=gwDispX;
	UINT16 wTop=gwDispY;	
	UINT16 wy,wx;

	if(TRUE==gfCcEnbaleShow) 	
	{
		if(TRUE!=gfCcShow)			
		{
			if(TRUE!=gfCcPreShow)
			{
				isdbtcc_osd_enter();
			}
			else
			{
				goto LEAVE;
			}
		} 
	}
	else
	{
		goto LEAVE;
	}	
	
	ENTER_SUBT_OSD_API();
		
	x = (x>bxend)?0:x;	
	y = (y>byend)?byend:y;	
	w = (w+x)>(bxend+1) ? ((bxend+1) -x) : w;
	h = (h+y)>(byend+1) ? ((byend+1) -y) : h;
	
	wy=y*bheight+wTop;
	wx=x*bwidth+wLeft;

	r.uLeft = wx;
	r.uTop = wy ;
	r.uWidth = w*bwidth;
	r.uHeight = h*bheight;

	pData = gVscr.lpbScr+gVscr.vR.uWidth*wy +wx;
	for(i=0;i<h*bheight;i++)
	{
		MEMSET(pData+gVscr.vR.uWidth*i,bg_color,w*bwidth);
	}
	
	#if (DBG_CS==1)
	OSDDrv_RegionFill((HANDLE)gOsdDev, gbCurRegion, &r,bg_color); 
	#endif
	
	LEAVE:
	LEAVE_SUBT_OSD_API();		
}

 void ICC_ClearScreen(UINT16 w, UINT16 h,UINT8 bg_color)
{
	UINT32 i;
	struct OSDRect r;	
	UINT8* pData; 
	UINT8 bwidth=gwCharX+gwSpaceX;
	UINT8 bheight=gwCharY+gwSpaceY;
	UINT16 wLeft=gwDispX;
	UINT16 wTop=gwDispY;	

	if(TRUE==gfCcEnbaleShow) 	
	{
		if(TRUE!=gfCcShow)			
		{
			if(TRUE!=gfCcPreShow)
			{
				isdbtcc_osd_enter();
			}
			else
			{
				goto LEAVE;
			}
		} 
	}
	else
	{
		goto LEAVE;
	}				

	ENTER_SUBT_OSD_API();		
	pData = gVscr.lpbScr+gVscr.vR.uWidth*wTop +wLeft;
	for(i=0;i<h*bheight;i++)
	{
		MEMSET(pData+gVscr.vR.uWidth*i,bg_color,w*bwidth);
	}
	
	#if (DBG_CS==1)	
	r.uLeft = wLeft;
	r.uTop = wTop ;
	r.uWidth = w*bwidth;
	r.uHeight = h*bheight;
	OSDDrv_RegionFill((HANDLE)gOsdDev, gbCurRegion, &r,bg_color); 
	#endif
	
	LEAVE:
	LEAVE_SUBT_OSD_API();	
}

#else
void ICC_FillChar(UINT16 x, UINT16 y,UINT16 w,UINT16 h,UINT8 bg_color)
{


	UINT32 i;
	struct OSDRect r;	
	UINT8* pData; 
	UINT8 bwidth=0;
	UINT16 wLeft=0;
	
	UINT8 bheight=gwCharY+gwSpaceY;
	UINT8 bxend=gbx2;
	UINT8 byend=gby2;

	UINT16 wTop=gwDispY;	
	UINT16 wy,wx;
	
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
		 bwidth=ISDBT_CC_FONT_WIDTH;
	else
		 bwidth=gwCharX+gwSpaceX;
	
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
		 wLeft=ISDBT_CC_OSD_LEFT;
	else		
		 wLeft=gwDispX;
	if(TRUE==gfCcEnbaleShow) 	
	{
		if(TRUE!=gfCcShow)			
		{
			if(TRUE!=gfCcPreShow)
			{
				isdbtcc_osd_enter();
			}
			else
			{
				goto LEAVE;
			}
		} 
	}
	else
	{
		goto LEAVE;
	}	
	
	ENTER_SUBT_OSD_API();
		
	x = (x>bxend)?0:x;	
	y = (y>byend)?byend:y;	
	w = (w+x)>(bxend+1) ? ((bxend+1) -x) : w;
	h = (h+y)>(byend+1) ? ((byend+1) -y) : h;
	
	wy=y*bheight+wTop;
	wx=x*bwidth+wLeft;
	gVscr.vR.uLeft =0;//r.uLeft;
	gVscr.vR.uTop = 0;//r.uTop;
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
		gVscr.vR.uWidth =ISDBT_CC_OSD_WIDTH;
	else
	gVscr.vR.uWidth =gwForX-gwDispX;
	gVscr.vR.uHeight =h*bheight;
	
	gVscr.lpbScr =g_isdbtcc_config_par.g_buf_addr;	
	
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
		pData = gVscr.lpbScr+y*bheight*ISDBT_CC_OSD_WIDTH+x*bwidth;
	else
	pData = gVscr.lpbScr+(y*bheight)*(gwForX-gwDispX)+x*bwidth;
	
	
	
	for(i=0;i<h*bheight;i++)
	{
		MEMSET(pData+(gVscr.vR.uWidth)*i,bg_color,w*bwidth);
	}
	
	r.uLeft =x*bwidth;
	r.uTop =y*bheight;
	r.uWidth =w*bwidth;
	r.uHeight = h*bheight;
	
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
		pData = gVscr.lpbScr+y*bheight*ISDBT_CC_OSD_WIDTH+x*bwidth;
	else
	pData = gVscr.lpbScr+(y*bheight)*(gwForX-gwDispX)+x*bwidth;
		
	
	#if (DBG_CS==1)
	OSDDrv_RegionFill((HANDLE)gOsdDev, gbCurRegion, &r,bg_color); 
	#endif
	
	LEAVE:
	LEAVE_SUBT_OSD_API();
	
}
void ICC_ClearScreen(UINT16 w, UINT16 h,UINT8 bg_color)
{
	UINT32 i;
	struct OSDRect r;	
	UINT8* pData; 
	UINT8 bwidth=0;
	UINT16 wLeft=0;
	
	UINT8 bheight=gwCharY+gwSpaceY;

	UINT16 wTop=gwDispY;
	
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
		 bwidth=ISDBT_CC_FONT_WIDTH;
	else
		 bwidth=gwCharX+gwSpaceX;
	
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
		 wLeft=ISDBT_CC_OSD_LEFT;
	else
		 wLeft=gwDispX;

	if(TRUE==gfCcEnbaleShow) 	
	{
		if(TRUE!=gfCcShow)			
		{
			if(TRUE!=gfCcPreShow)
			{
				isdbtcc_osd_enter();
			}
			else
			{
				goto LEAVE;
			}
		} 
	}
	else
	{
		goto LEAVE;
	}				

	ENTER_SUBT_OSD_API();	
	gVscr.vR.uLeft =0;
	gVscr.vR.uTop = 0;
	if(g_isdbtcc_config_par.isdbtcc_fontsize_changed==TRUE)
		gVscr.vR.uWidth =w*bwidth;
	else
	gVscr.vR.uWidth =gwForX-gwDispX;
	gVscr.vR.uHeight =h*bheight;
	
	gVscr.lpbScr =g_isdbtcc_config_par.g_buf_addr;	
	
	pData = gVscr.lpbScr;
	
	for(i=0;i<h*bheight;i++)
	{
		MEMSET(pData+gVscr.vR.uWidth*i,bg_color,w*bwidth);
	}
	
	#if (DBG_CS==1)	
	r.uLeft = 0;
	r.uTop = 0 ;
	r.uWidth = w*bwidth;
	r.uHeight = h*bheight;
	OSDDrv_RegionFill((HANDLE)gOsdDev, gbCurRegion, &r,bg_color); 
	#endif
	
	LEAVE:
	LEAVE_SUBT_OSD_API();	
}

#endif
 void ICC_UpdateScreen(void)
 {	
 	#if (DBG_CS==1)
		return;
	#elif (DBG_CS==2)
	struct OSDRect r;	
	r.uLeft = 0;
	r.uTop = 0;
	r.uWidth = gwForX;
	r.uHeight = gwForY;
	OSDDrv_RegionWrite((HANDLE)gOsdDev, gbCurRegion, &gVscr, &r);
	#endif
 }
